home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Blender 2.49b / blender-2.49b-windows.exe / $_4_ / .blender / scripts / bpymodules / BPyArmature.py < prev    next >
Text File  |  2009-08-31  |  6KB  |  153 lines

  1. # This program is free software; you can redistribute it and/or modify
  2. # it under the terms of the GNU General Public License as published by
  3. # the Free Software Foundation; either version 2 of the License, or
  4. # (at your option) any later version.
  5. #
  6. # This program is distributed in the hope that it will be useful,
  7. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9. # GNU General Public License for more details.
  10. #
  11. # You should have received a copy of the GNU General Public License
  12. # along with this program; if not, write to the Free Software
  13. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  14. # Version History:
  15. #   1.0 original release bakes an armature into a matrix
  16. #   1.1 optional params (ACTION_BAKE, ACTION_BAKE_FIRST_FRAME, direct function to key and return the Action
  17.  
  18. import Blender
  19. from Blender import sys
  20. import bpy
  21. def getBakedPoseData(ob_arm, start_frame, end_frame, ACTION_BAKE = False, ACTION_BAKE_FIRST_FRAME = True):
  22.     '''
  23.     If you are currently getting IPO's this function can be used to
  24.     ACTION_BAKE==False: return a list of frame aligned bone dictionary's
  25.     ACTION_BAKE==True: return an action with keys aligned to bone constrained movement
  26.     if ACTION_BAKE_FIRST_FRAME is not supplied or is true: keys begin at frame 1
  27.     
  28.     The data in these can be swaped in for the IPO loc and quat
  29.     
  30.     If you want to bake an action, this is not as hard and the ipo hack can be removed.
  31.     '''
  32.     
  33.     # --------------------------------- Dummy Action! Only for this functon
  34.     backup_action = ob_arm.action
  35.     backup_frame = Blender.Get('curframe')
  36.     
  37.     DUMMY_ACTION_NAME = '~DONT_USE~'
  38.     # Get the dummy action if it has no users
  39.     try:
  40.         new_action = bpy.data.actions[DUMMY_ACTION_NAME]
  41.         if new_action.users:
  42.             new_action = None
  43.     except:
  44.         new_action = None
  45.     
  46.     if not new_action:
  47.         new_action = bpy.data.actions.new(DUMMY_ACTION_NAME)
  48.         new_action.fakeUser = False
  49.     # ---------------------------------- Done
  50.     
  51.     Matrix = Blender.Mathutils.Matrix
  52.     Quaternion = Blender.Mathutils.Quaternion
  53.     Vector = Blender.Mathutils.Vector
  54.     POSE_XFORM= [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT]
  55.     
  56.     # Each dict a frame
  57.     bake_data = [{} for i in xrange(1+end_frame-start_frame)]
  58.     
  59.     pose=            ob_arm.getPose()
  60.     armature_data=    ob_arm.getData();
  61.     pose_bones=        pose.bones
  62.     
  63.     # --------------------------------- Build a list of arma data for reuse
  64.     armature_bone_data = []
  65.     bones_index = {}
  66.     for bone_name, rest_bone in armature_data.bones.items():
  67.         pose_bone = pose_bones[bone_name]
  68.         rest_matrix = rest_bone.matrix['ARMATURESPACE']
  69.         rest_matrix_inv = rest_matrix.copy().invert()
  70.         armature_bone_data.append( [len(bones_index), -1, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, None ])
  71.         bones_index[bone_name] = len(bones_index)
  72.     
  73.     # Set the parent ID's
  74.     for bone_name, pose_bone in pose_bones.items():
  75.         parent = pose_bone.parent
  76.         if parent:
  77.             bone_index= bones_index[bone_name]
  78.             parent_index= bones_index[parent.name]
  79.             armature_bone_data[ bone_index ][1]= parent_index
  80.     # ---------------------------------- Done
  81.     
  82.     
  83.     
  84.     # --------------------------------- Main loop to collect IPO data
  85.     frame_index = 0
  86.     NvideoFrames= end_frame-start_frame
  87.     for current_frame in xrange(start_frame, end_frame+1):
  88.         if   frame_index==0: start=sys.time()
  89.         elif frame_index==15: print NvideoFrames*(sys.time()-start),"seconds estimated..." #slows as it grows *3
  90.         elif frame_index >15:
  91.             percom= frame_index*100/NvideoFrames
  92.             print "Frame %i Overall %i percent complete\r" % (current_frame, percom),
  93.         ob_arm.action = backup_action
  94.         #pose.update() # not needed
  95.         Blender.Set('curframe', current_frame)
  96.         #Blender.Window.RedrawAll()
  97.         #frame_data = bake_data[frame_index]
  98.         ob_arm.action = new_action
  99.         ###for i,pose_bone in enumerate(pose_bones):
  100.         
  101.         for index, parent_index, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, ipo in armature_bone_data:
  102.             matrix= pose_bone.poseMatrix
  103.             parent_bone= rest_bone.parent
  104.             if parent_index != -1:
  105.                 parent_pose_matrix =        armature_bone_data[parent_index][6].poseMatrix
  106.                 parent_bone_matrix_inv =    armature_bone_data[parent_index][5]
  107.                 matrix=                        matrix * parent_pose_matrix.copy().invert()
  108.                 rest_matrix=                rest_matrix * parent_bone_matrix_inv
  109.             
  110.             matrix=matrix * rest_matrix.copy().invert()
  111.             pose_bone.quat=    matrix.toQuat()
  112.             pose_bone.loc=    matrix.translationPart()
  113.             if ACTION_BAKE==False:
  114.                 pose_bone.insertKey(ob_arm, 1, POSE_XFORM) # always frame 1
  115.      
  116.                 # THIS IS A BAD HACK! IT SUCKS BIGTIME BUT THE RESULT ARE NICE
  117.                 # - use a temp action and bake into that, always at the same frame
  118.                 #   so as not to make big IPO's, then collect the result from the IPOs
  119.             
  120.                 # Now get the data from the IPOs
  121.                 if not ipo:    ipo = armature_bone_data[index][7] = new_action.getChannelIpo(bone_name)
  122.             
  123.                 loc = Vector()
  124.                 quat  = Quaternion()
  125.             
  126.                 for curve in ipo:
  127.                     val = curve.evaluate(1)
  128.                     curve_name= curve.name
  129.                     if   curve_name == 'LocX':  loc[0] = val
  130.                     elif curve_name == 'LocY':  loc[1] = val
  131.                     elif curve_name == 'LocZ':  loc[2] = val
  132.                     elif curve_name == 'QuatW': quat[3]  = val
  133.                     elif curve_name == 'QuatX': quat[0]  = val
  134.                     elif curve_name == 'QuatY': quat[1]  = val
  135.                     elif curve_name == 'QuatZ': quat[2]  = val
  136.             
  137.                 bake_data[frame_index][bone_name] = loc, quat
  138.             else:
  139.                 if ACTION_BAKE_FIRST_FRAME: pose_bone.insertKey(ob_arm, frame_index+1,  POSE_XFORM)
  140.                 else:           pose_bone.insertKey(ob_arm, current_frame , POSE_XFORM)
  141.         frame_index+=1
  142.     print "\nBaking Complete."
  143.     ob_arm.action = backup_action
  144.     if ACTION_BAKE==False:
  145.         Blender.Set('curframe', backup_frame)
  146.         return bake_data
  147.     elif ACTION_BAKE==True:
  148.         return new_action
  149.     else: print "ERROR: Invalid ACTION_BAKE %i sent to BPyArmature" % ACTION_BAKE
  150.  
  151.  
  152.  
  153.